﻿using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;

namespace XKPlatform.DataModels
{
    public static class StringExtensions
    {
        public static short StringToShort(this string str, short defValue = 0)
        {
            short ret;
            if (short.TryParse(str, out ret))
            {
                return ret;
            }

            return defValue;
        }
        public static short ObjectToShort(this object str, short defValue = 0)
        {
            short ret;
            if (str == null)
            {
                return 0;
            }
            if (short.TryParse(str.ToString(), out ret))
            {
                return ret;
            }

            return defValue;
        }

        public static Boolean ObjectToBoolean(this object obj, bool defValue = false)
        {
            if (obj == null)
            {
                return false;
            }
            bool ret;
            if (Boolean.TryParse(obj.ToString(), out ret))
            {
                return ret;
            }
            return defValue;
        }

        public static int StringToInt(this string str, int defValue = 0)
        {
            int ret;
            if (int.TryParse(str, out ret))
            {
                return ret;
            }

            return defValue;
        }
        public static int ObjectToInt(this object str, int defValue = 0)
        {
            int ret;
            if (str == null)
            {
                return 0;

            }
            if (int.TryParse(str.ToString(), out ret))
            {
                return ret;
            }

            return defValue;
        }



        public static long ObjectToInt64(this object str, long defValue = 0)
        {
            long ret;
            if (str == null)
            {
                return 0;

            }
            if (long.TryParse(str.ToString(), out ret))
            {
                return ret;
            }

            return defValue;
        }


        public static long StringToInt64(this string str, long defValue = 0)
        {
            long ret;
            if (long.TryParse(str, out ret))
            {
                return ret;
            }

            return defValue;
        }

        public static decimal StringToDecimal(this string str, decimal defValue = 0)
        {
            decimal ret;
            if (decimal.TryParse(str, out ret))
            {
                return ret;
            }

            return defValue;
        }

        public static decimal ObjectToDecimal(this object str, decimal defValue = 0)
        {
            if (str == null)
            {
                return 0;
            }
            decimal ret;
            if (decimal.TryParse(str.ToString(), out ret))
            {
                return ret;
            }

            return defValue;
        }

        public static DateTime? ObjectToDateTime(this object obj)
        {
            if (obj == null)
            {
                return null;
            }
            try
            {
                return Convert.ToDateTime(obj);
            }
            catch (Exception ex)
            {
                return null;
            }
        }

        //public static bool IsNullOrEmpty(this string str)
        //{
        //    return string.IsNullOrEmpty(str);
        //}

        public static string ReplaceFirst(this string str, string str1, string str2)
        {
            var regex = new Regex(Regex.Escape(str1));
            var newText = regex.Replace(str, str2, 1);
            return newText;
        }


        public static bool IsNullOrWhiteSpace(this string str)
        {
            return string.IsNullOrWhiteSpace(str);
        }

        public static T ToObj<T>(this string str)
        {
            try
            {
                return JsonConvert.DeserializeObject<T>(str);
            }
            catch (Exception)
            {
                return default(T);
            }
        }

        public static byte[] ToBytes(this string str)
        {
            return Encoding.UTF8.GetBytes(str);
        }

        public static byte[] ToBytes(this object str)
        {
            if (str == null)
            {
                return null;
            }
            return Encoding.UTF8.GetBytes(str.ToString());
        }


        public static string ReleceSql(this string aSqlStr)
        {
            aSqlStr = Regex.Replace(aSqlStr, "--", "—", RegexOptions.IgnoreCase);
            aSqlStr = Regex.Replace(aSqlStr, "'", "‘", RegexOptions.IgnoreCase);
            aSqlStr = aSqlStr.Replace(@"{", @"《");
            aSqlStr = aSqlStr.Replace(@"}", @"》");
            aSqlStr = aSqlStr.Replace(@"[", @"【");
            aSqlStr = aSqlStr.Replace(@"]", @"】");


            return aSqlStr;
        }


        public static List<string> SplitCsv(this string csvList, bool nullOrWhitespaceInputReturnsNull = false)
        {
            if (string.IsNullOrWhiteSpace(csvList))
                return nullOrWhitespaceInputReturnsNull ? null : new List<string>();

            return csvList
                .TrimEnd(',')
                .Split(',')
                .AsEnumerable<string>()
                .Select(s => s.Trim())
                .ToList();
        }

        public static bool IsNullOrWhitespace(this string s)
        {
            return String.IsNullOrWhiteSpace(s);
        }


        #region To Bool

        /// <summary>
        /// 只有'True'或'true'可以转换，'Y'或'1'不可以转换，转换不成功返回false
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public static bool ToBool(this string str)
        {
            return str.ToBool(false);
        }

        /// <summary>
        /// 只有'True'或'true'可以转换，'Y'或'1'不可以转换，转换不成功返回默认值
        /// </summary>
        /// <param name="str"></param>
        /// <param name="defaultValue"></param>
        /// <returns></returns>
        public static bool ToBool(this string str, bool defaultValue)
        {
            bool b;
            if (bool.TryParse(str, out b))
            {
                return b;
            }
            else
            {
                return defaultValue;
            }
        }

        ///// <summary>
        ///// 只有'True'或'true'可以转换，'Y'或'1'不可以转换，转换不成功则返回null
        ///// </summary>
        ///// <param name="str"></param>
        ///// <returns></returns>
        //public static bool? ToBoolOrNull(this string str)
        //{
        //    bool temp;
        //    if (bool.TryParse(str, out temp))
        //        return temp;
        //    else
        //        return null;
        //}

        /// <summary>
        /// 'True','true','Y'和'1'都可以转换，转换不成功返回false
        /// </summary>
        /// <param name="s"></param>
        /// <returns></returns>
        public static bool ToBoolNew(this string s)
        {
            if (s == null)
            {
                return false;
            }
            s = s.Trim();

            return string.Equals(s, "True", StringComparison.CurrentCultureIgnoreCase)
                || string.Equals(s, "Y", StringComparison.CurrentCultureIgnoreCase)
                || s == "1";
        }

        #endregion

        #region To DateTime
        /// <summary>
        /// 转换时间，如果转换失败则返回预设值
        /// </summary>
        /// <param name="str"></param>
        /// <param name="defaultValue"></param>
        /// <returns></returns>
        public static DateTime? ToDateTimeOrNull(this string str, DateTime? defaultValue = null)
        {
            DateTime d;
            if (DateTime.TryParse(str, out d))
            {
                return d;
            }
            else
            {
                if (DateTime.TryParseExact(str, new string[] { "yyyy-MM-dd", "yyyy-MM-dd HH:mm:ss", "yyyyMMdd", "yyyyMMdd HH:mm:ss", "yyyy/MM/dd", "yyyy'/'MM'/'dd HH:mm:ss", "MM'/'dd'/'yyyy HH:mm:ss", "yyyy-M-d", "yyy-M-d hh:mm:ss" }, CultureInfo.InvariantCulture, DateTimeStyles.AdjustToUniversal, out d))
                {
                    return d;
                }
                else
                {
                    return defaultValue;
                }
            }
        }

        /// <summary>
        /// 转换时间，按给定的日期格式进行转换，转换失败返回Null
        /// </summary>
        /// <param name="str"></param>
        /// <param name="dateFmt"></param>
        /// <param name="defaultValue"></param>
        /// <returns></returns>
        public static DateTime? ToDateTimeOrNull(this string str, string dateFmt, DateTime? defaultValue = null)
        {
            DateTime d;
            if (DateTime.TryParseExact(str, dateFmt, CultureInfo.InvariantCulture, DateTimeStyles.AdjustToUniversal, out d))
            {
                return d;
            }
            else
            {
                return defaultValue;
            }
        }

        /// <summary>
        /// 转换时间，如果转换失败则返回defaultValue
        /// </summary>
        /// <param name="str"></param>
        /// <param name="defaultValue"></param>
        /// <returns></returns>
        public static DateTime ToDateTime(this string str, DateTime defaultValue = default(DateTime))
        {
            DateTime d;
            if (DateTime.TryParse(str, out d))
            {
                return d;
            }
            else
            {
                if (DateTime.TryParseExact(str, new string[] { "yyyy-MM-dd", "yyyy-MM-dd HH:mm:ss", "yyyyMMdd", "yyyyMMdd HH:mm:ss", "yyyy/MM/dd", "yyyy/MM/dd HH:mm:ss", "MM/dd/yyyy HH:mm:ss" }, CultureInfo.InvariantCulture, DateTimeStyles.AdjustToUniversal, out d))
                {
                    return d;
                }
                else
                {
                    return defaultValue;
                }
            }
        }

        /// <summary>
        /// 转换时间，按给定的日期格式进行转换
        /// </summary>
        /// <param name="str"></param>
        /// <param name="dateFmt"></param>
        /// <param name="defaultValue"></param>
        /// <returns></returns>
        public static DateTime ToDateTime(this string str, string dateFmt, DateTime defaultValue)
        {
            DateTime d;
            if (DateTime.TryParseExact(str, dateFmt, CultureInfo.InvariantCulture, DateTimeStyles.AdjustToUniversal, out d))
            {
                return d;
            }
            else
            {
                return defaultValue;
            }
        }

        /// <summary>
        /// 转换时间，如果转换失败则返回Null
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public static DateTime? ToDateTimeOrNull(this string str)
        {
            return str.ToDateTimeOrNull(null);
        }

        /// <summary>
        /// 转换时间，如果转换失败则返回当前时间
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public static DateTime ToDateTime(this string str)
        {
            return str.ToDateTime(DateTime.Now);
        }

        #endregion

        #region To TimeSpan

        /// <summary>
        /// 字符串转TimeSpan
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public static TimeSpan ToTimeSpan(this string str)
        {
            return str.ToTimeSpan(new TimeSpan());
        }

        /// <summary>
        /// 字符串转TimeSpan，转换失败时返回默认值
        /// </summary>
        /// <param name="str"></param>
        /// <param name="defaultValue"></param>
        /// <returns></returns>
        public static TimeSpan ToTimeSpan(this string str, TimeSpan defaultValue)
        {
            TimeSpan t;
            if (TimeSpan.TryParse(str, out t))
            {
                return t;
            }
            else
            {
                return defaultValue;
            }
        }

        #endregion

        #region To Guid
        public static Guid ToGuid(this string str)
        {
            Guid defaultValue = Guid.Empty;

            return ToGuid(str, defaultValue);
        }

        public static Guid ToGuid(this string str, Guid defaultValue)
        {
            if (str == null || str.Length == 0)
            {
                return defaultValue;
            }
            return new Guid(str);
        }
        #endregion

        #region To Float

        /// <summary>
        /// 字符串转float，转换失败返回0
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public static float ToFloat(this string str)
        {
            return str.ToFloat(0f);
        }

        /// <summary>
        /// 字符串转float，转换失败返回默认值
        /// </summary>
        /// <param name="str"></param>
        /// <param name="defaultValue"></param>
        /// <returns></returns>
        public static float ToFloat(this string str, float defaultValue)
        {
            float v;
            if (float.TryParse(str, out v))
            {
                return v;
            }
            else
            {
                return defaultValue;
            }
        }

        /// <summary>
        /// 智能转换float
        /// </summary>
        /// <param name="str"></param>
        /// <param name="defaultValue"></param>
        /// <returns></returns>
        public static float SmartToFloat(this string str, float defaultValue)
        {
            if (string.IsNullOrEmpty(str))
            {
                return defaultValue;
            }

            Regex rx = new Regex(@"((-\s*)?(\d+)(\.?((?=\d)\d+))?(e[\+-]?\d+)*)");
            Match ma = rx.Match(str);
            if (ma.Success)
            {
                return ma.Groups[1].Value.Replace(" ", "").ToFloat(defaultValue);
            }
            else
            {
                return defaultValue;
            }
        }

        #endregion

        #region To Double

        /// <summary>
        /// 字符串转double，转换失败返回0
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public static double ToDouble(this string str)
        {
            return str.ToDouble(0);
        }

        /// <summary>
        /// 字符串转double，转换失败返回Null
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public static double? ToDoubleOrNull(this string str)
        {
            double temp;
            if (double.TryParse(str, out temp))
            {
                return temp;
            }
            else
            {
                return null;
            }
        }

        /// <summary>
        /// 字符串转double，转换失败返回默认值
        /// </summary>
        /// <param name="str"></param>
        /// <param name="defaultValue"></param>
        /// <returns></returns>
        public static double ToDouble(this string str, double defaultValue)
        {
            double v;
            if (double.TryParse(str, NumberStyles.Any, null, out v))
            {
                return v;
            }
            else
            {
                return defaultValue;
            }
        }

        #endregion
    }
}
